package com.qianfeng.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.socket.config.annotation.EnableWebSocket;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/*
 *@Description:
 *@author:刘哥
 *@Date:86180 2022/9/1 14:44
 */
@Configuration//声明当前类是配置类
@EnableTransactionManagement
@EnableAsync(proxyTargetClass = true)//开启异步
@EnableScheduling//开启定时任务注解
public class BeanConfig {

    /**
     * 密码的编码器
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //    配置连接
    @Bean
    public DruidDataSource datasource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/smartplatform?useSSL=false&characterEncoding=UTF8");
        dataSource.setUsername("root");
        dataSource.setPassword("2682933037xc.");
        return dataSource;
    }
//    配置sqlsession
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource druidDataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(druidDataSource);
        sqlSessionFactoryBean.setPlugins(new PageInterceptor());
        sqlSessionFactoryBean.setTypeAliasesPackage("com.qianfeng.pojo");
//        添加设置
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//       设置驼峰映射
        configuration.setMapUnderscoreToCamelCase(true);
//        设置日志
        configuration.setLogImpl(StdOutImpl.class);
//        开启设置
        sqlSessionFactoryBean.setConfiguration(configuration);
        return sqlSessionFactoryBean;
    }
//    配置mapper
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.qianfeng.mapper");
        return configurer;
    }
//    配置事务管理器
    @Bean
    public DataSourceTransactionManager transactionManager(DruidDataSource druidDataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(druidDataSource);
        return transactionManager;

    }
//    配置线程池
    @Bean
    public TaskExecutor taskExecutor(){
        ThreadPoolTaskExecutor taskExecutor=new ThreadPoolTaskExecutor();
//       设置线程池核心数大小
        taskExecutor.setCorePoolSize(15);
        taskExecutor.setMaxPoolSize(20);
//        设置线程的前缀名称
        taskExecutor.setThreadNamePrefix("bk2205-");
        return taskExecutor;
    }

    /** sprignwebsocket注解和task注解冲突
     * org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'defaultSockJsTaskScheduler' is expected to be of type 'org.springframework.scheduling.TaskScheduler' but was actually of type 'org.springframework.beans.factory.support.NullBean'
     * @return
     */
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler threadPoolScheduler = new ThreadPoolTaskScheduler();
        threadPoolScheduler.setThreadNamePrefix("SockJS-");
        threadPoolScheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
        threadPoolScheduler.setRemoveOnCancelPolicy(true);
        return threadPoolScheduler;
    }

    /**
     * ObjectMapper类(com.fasterxml.jackson.databind.ObjectMapper)是Jackson的主要类，它可以帮助我们快速的进行各个类型和Json类型的相互转换。
     * @return
     */
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
/*
    配置线程池
 */
    @Bean
    public ThreadPoolExecutor complateFutureExecutor() {

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                120,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(20),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        return executor;
    }
}
